#include "client.hpp"

/**
 * @brief 初始化命令手册和命令函数映射关系
 *
 */
Client::Client()
{
    commandMap["help"] = "显示所有支持的命令，格式|help";
    commandMap["onechat"] = "一对一聊天，格式|onechat:friendid:message";
    commandMap["addfriend"] = "添加好友，格式|addfriend:friendid";
    commandMap["creategroup"] = "创建群组，格式|creategroup:groupname:groupdesc";
    commandMap["addgroup"] = "加入群组，格式|addgroup:groupid";
    commandMap["groupchat"] = "群聊，格式|groupchat:groupid:message";
    commandMap["loginout"] = "注销，格式|loginout";

    commandHandlerMap["help"] = bind(&Client::help, this, _1, _2);
    commandHandlerMap["onechat"] = bind(&Client::onechat, this, _1, _2);
    commandHandlerMap["addfriend"] = bind(&Client::addfriend, this, _1, _2);
    commandHandlerMap["creategroup"] = bind(&Client::creategroup, this, _1, _2);
    commandHandlerMap["addgroup"] = bind(&Client::addgroup, this, _1, _2);
    commandHandlerMap["groupchat"] = bind(&Client::groupchat, this, _1, _2);
    commandHandlerMap["loginout"] = bind(&Client::loginout, this, _1, _2);
}
/**
 * @brief client登录后运行主菜单
 *
 * @param clientfd
 */
void Client::mainMenu(int clientfd)
{
    help();
    char buffer[1024] = {0};
    while (true)
    {
        cin.getline(buffer, 1024);
        string commandbuf(buffer);
        string command; // 存储命令
        int idx = commandbuf.find(":");
        if (-1 == idx)
        {
            command = commandbuf;
        }
        else
        {
            command = commandbuf.substr(0, idx);
        }
        auto it = commandHandlerMap.find(command);
        if (it == commandHandlerMap.end())
        {
            cerr << "invalid input command!" << endl;
        }
        else
        {
            //  调用相应命令的事件处理回调
            it->second(clientfd, commandbuf.substr(idx + 1));
            if (command == "loginout")
            {
                break;
            }
        }
    }
}
/**
 * @brief 帮助功能 help
 *
 * @param clientfd
 * @param str
 */
void Client::help(int clientfd, string str)
{
    cout << "show command list >>> " << endl;
    for (auto &p : commandMap)
    {
        cout << p.first << " : " << p.second << endl;
    }
    cout << endl;
}
/**
 * @brief 聊天功能 chat:friendid:message
 *
 * @param clientfd
 * @param str
 */
void Client::onechat(int clientfd, string str)
{
    int idx = str.find(':');
    if (idx == -1)
    {
        cerr << "onechat command invalid!" << endl;
        return;
    }
    int friendid = atoi(str.substr(0, idx).c_str());
    string message = str.substr(idx + 1);

    json js;
    js["msgid"] = ONE_CHAT_MSG;
    js["id"] = user.getId();
    js["name"] = user.getName();
    js["friendid"] = friendid;
    js["msg"] = message;
    js["time"] = getCurrentTime();

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send onechat msg error: " << buffer << endl;
    }
}
/**
 * @brief 添加好友功能 addfriend:friendid
 *
 * @param clientfd
 * @param str
 */
void Client::addfriend(int clientfd, string str)
{
    int friendid = atoi(str.c_str());

    json js;
    js["msgid"] = ADD_FRIEND_MSG;
    js["id"] = user.getId();
    js["friendid"] = friendid;

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send addfriend msg error: " << buffer << endl;
    }
}
/**
 * @brief 退出功能 loginout
 *
 * @param clientfd
 * @param str
 */
void Client::loginout(int clientfd, string str)
{
    json js;
    js["msgid"] = LOGIN_OUT_MSG;
    js["id"] = user.getId();

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send loginout msg error: " << buffer << endl;
    }
    // exit(0);
}
/**
 * @brief 建群功能 creategroup:groupname:groupdesc
 *
 * @param clientfd
 * @param str
 */
void Client::creategroup(int clientfd, string str)
{
    int idx = str.find(':');
    if (idx == -1)
    {
        cerr << "creategroup command invalid!" << endl;
        return;
    }
    string groupname = str.substr(0, idx);
    string groupdesc = str.substr(idx + 1);

    json js;
    js["msgid"] = CREATE_GROUP_MSG;
    js["id"] = user.getId();
    js["groupname"] = groupname;
    js["groupdesc"] = groupdesc;

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send creategroup msg error: " << buffer << endl;
    }
}
/**
 * @brief 加群功能 addgroup:groupid
 *
 * @param clientfd
 * @param str
 */
void Client::addgroup(int clientfd, string str)
{
    int groupid = atoi(str.c_str());

    json js;
    js["msgid"] = ADD_GROUP_MSG;
    js["id"] = user.getId();
    js["groupid"] = groupid;

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send addgroup msg error: " << buffer << endl;
    }
}
/**
 * @brief 群聊功能 groupchat:groupid:message
 *
 * @param clientfd
 * @param str
 */
void Client::groupchat(int clientfd, string str)
{
    int idx = str.find(':');
    if (idx == -1)
    {
        cerr << "groupchat command invalid!" << endl;
        return;
    }
    int groupid = atoi(str.substr(0, idx).c_str());
    string message = str.substr(idx + 1);
    json js;
    js["msgid"] = GROUP_CHAT_MSG;
    js["id"] = user.getId();
    js["name"] = user.getName();
    js["groupid"] = groupid;
    js["msg"] = message;
    js["time"] = getCurrentTime();

    string buffer = js.dump();
    int len = send(clientfd, buffer.c_str(), strlen(buffer.c_str()) + 1, 0);
    if (len == -1)
    {
        cerr << "send groupchat msg error: " << buffer << endl;
    }
}
/**
 * @brief 客户端登录数据初始化
 *
 * @param js
 * @return true
 * @return false
 */
bool Client::loginResponse(json &js)
{
    if (js["errno"].get<int>() != 0)
    {
        cerr << js["errmsg"].get<string>() << endl;
        return false;
    }
    int id = js["id"].get<int>();
    user.setId(id);
    user.setName(js["name"]);
    if (js.contains("friends"))
    {
        friendList.clear();
        vector<string> v = js["friends"];
        for (string &str : v)
        {
            json u_js = json::parse(str);
            User user;
            user.setId(u_js["id"].get<int>());
            user.setName(u_js["name"]);
            user.setState(u_js["state"]);
            friendList.push_back(user);
        }
    }
    if (js.contains("groups"))
    {
        groupList.clear();
        vector<string> v = js["groups"];
        for (string &str : v)
        {
            json g_js = json::parse(str);
            Group group;
            group.setId(g_js["groupid"].get<int>());
            group.setName(g_js["groupname"]);
            group.setDesc(g_js["groupdesc"]);

            vector<string> vec = g_js["groupusers"];
            for (string &ustr : vec)
            {
                json gu_js = json::parse(ustr);
                GroupUser guser;
                guser.setId(gu_js["id"].get<int>());
                guser.setName(gu_js["name"]);
                guser.setState(gu_js["state"]);
                guser.setRole(gu_js["role"]);
                group.getUsers().push_back(guser);
            }
            groupList.push_back(group);
        }
    }
    showCurrentUserData();
    if (js.contains("offlinemessage"))
    {
        vector<string> v = js["offlinemessage"];
        for (string &str : v)
        {
            json msgjs = json::parse(str);
            if (msgjs["msgid"].get<int>() == ONE_CHAT_MSG)
            {
                cout << "[" << msgjs["time"].get<string>() << "][FriendId:" << msgjs["id"] << "][" << msgjs["name"].get<string>() << "]"
                     << " said: " << msgjs["msg"].get<string>() << endl;
            }
            else
            {
                cout << "[" << msgjs["time"].get<string>() << "][GroupId:" << msgjs["groupid"] << "][FriendId:" << msgjs["id"] << "][" << msgjs["name"].get<string>() << "]"
                     << " said: " << msgjs["msg"].get<string>() << endl;
            }
        }
    }
    return true;
}
/**
 * @brief 获取当前时间
 *
 * @return string
 */
string Client::getCurrentTime()
{
    auto tt = system_clock::to_time_t(system_clock::now());
    struct tm *ptm = localtime(&tt);
    char date[60] = {0};
    sprintf(date, "%d-%02d-%02d %02d:%02d:%02d",
            (int)ptm->tm_year + 1900, (int)ptm->tm_mon + 1, (int)ptm->tm_mday,
            (int)ptm->tm_hour, (int)ptm->tm_min, (int)ptm->tm_sec);
    return string(date);
}
/**
 * @brief 展示用户信息
 *
 */
void Client::showCurrentUserData()
{
    cout << "======================login user======================" << endl;
    cout << "current login user => [id:" << user.getId() << "][name:" << user.getName() << "]" << endl;
    cout << "----------------------friend list---------------------" << endl;
    if (!friendList.empty())
    {
        for (User &user : friendList)
        {
            cout << "[" << user.getId() << "][" << user.getName() << "][" << user.getState() << "]" << endl;
        }
    }
    cout << "----------------------group list----------------------" << endl;
    if (!groupList.empty())
    {
        for (Group &group : groupList)
        {
            cout << "[" << group.getId() << "][" << group.getName() << "][" << group.getDesc() << "]" << endl;
            for (GroupUser &user : group.getUsers())
            {
                cout << "[" << user.getId() << "-" << user.getName() << "-" << user.getState() << "-" << user.getRole() << "]" << endl;
            }
        }
    }
    cout << "======================================================" << endl;
}